package com.muqiuhan.osmanthus.serializer

import java.io.{ByteArrayInputStream, ByteArrayOutputStream, IOException, ObjectInputStream, ObjectOutputStream}
import scala.util.{Failure, Success, Try}

class JDKSerializationSerializer[T] extends AnyRefSerializer[T]:

  private implicit class ByteArrayOutputStreamWriteObject(outputStream: ByteArrayOutputStream):
    inline def writeObject(t: T): Unit =
      val objectOutputStream = ObjectOutputStream(outputStream)
      objectOutputStream.writeObject(t)
      objectOutputStream.flush()
    end writeObject
  end ByteArrayOutputStreamWriteObject

  override def serialize(t: T): Option[Array[Byte]] =
    t match
      case null => None
      case _ =>
        val outputStream = new ByteArrayOutputStream(1024)
        Try(outputStream.writeObject(t)) match
          case Failure(e: IOException) => throw IllegalArgumentException(s"Failed to serialize object type ${t.getClass}", e)
          case Success(_)              => Some(outputStream.toByteArray)
          case Failure(_)              => throw RuntimeException("Failed to serialize object")
        end match
    end match
  end serialize

  override def deserialize(bytes: Array[Byte]): Option[T] =
    bytes match
      case null => None
      case _ =>
        Try(new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject()) match
          case Failure(e: IOException)            => throw IllegalArgumentException("Failed to deserialize object", e)
          case Failure(e: ClassNotFoundException) => throw IllegalStateException("Failed to deserialize object type", e)
          case Success(t)                         => Some(t.asInstanceOf[T])
          case scala.util.Failure(_)              => throw RuntimeException("Failed to deserialize object")
        end match
    end match
  end deserialize

end JDKSerializationSerializer
